/* This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package Controlador.Informe;

import Controlador.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
import java.awt.Color;

import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.*;
import Modelo.*;

/**
 * Clase que permite escribir y firmar informes pdf con los resultados de los analisis de la aplicacion
 */
public class GestorInformesPDF {

    /**
     * Constructor de la clase GestorInformesPDF
     */
    public GestorInformesPDF() {
    }

    /**
     * Metodo que permite escribir un informe en PDF
     * @param fichero Fichero de salida
     * @param analizador Objeto analizador que incluye el conjunto de plugins y resultados.
     */
    public void escribirInformePDF(String fichero, Analizador analizador) {

        Vector plugins = analizador.getPlugins();
        Vector acciones = analizador.getAccionador()._acciones;
        Document documento = new Document(PageSize.A4, 36, 36, 36, 36);
        // the 14 standard fonts in PDF: do not use this Font constructor!
        // this is for demonstration purposes only, use FontFactory!
        Font[] fonts = new Font[14];
        fonts[0] = new Font(Font.COURIER, Font.DEFAULTSIZE, Font.NORMAL);
        fonts[1] = new Font(Font.COURIER, Font.DEFAULTSIZE, Font.ITALIC);
        fonts[2] = new Font(Font.COURIER, Font.DEFAULTSIZE, Font.BOLD);
        fonts[3] = new Font(Font.COURIER, Font.DEFAULTSIZE, Font.BOLD | Font.ITALIC);
        fonts[4] = new Font(Font.HELVETICA, Font.DEFAULTSIZE, Font.NORMAL);
        fonts[5] = new Font(Font.HELVETICA, Font.DEFAULTSIZE, Font.ITALIC);
        fonts[6] = new Font(Font.HELVETICA, Font.DEFAULTSIZE, Font.BOLD);
        fonts[7] = new Font(Font.HELVETICA, Font.DEFAULTSIZE, Font.BOLDITALIC);
        fonts[8] = new Font(Font.TIMES_ROMAN, Font.DEFAULTSIZE, Font.NORMAL);
        fonts[9] = new Font(Font.TIMES_ROMAN, Font.DEFAULTSIZE, Font.ITALIC);
        fonts[10] = new Font(Font.TIMES_ROMAN, 14, Font.BOLD);
        fonts[11] = new Font(Font.TIMES_ROMAN, 20, Font.BOLDITALIC);
        fonts[12] = new Font(Font.SYMBOL);
        fonts[13] = new Font(Font.ZAPFDINGBATS);
        Font red = FontFactory.getFont(FontFactory.HELVETICA, 11, Font.BOLD, new Color(0xFF, 0x00, 0x00));
        Font blue = FontFactory.getFont(FontFactory.HELVETICA, 11, Font.ITALIC, new Color(0x00, 0x00, 0xFF));
        java.util.Date fechaActual = new java.util.Date(); //Fecha actual del sistema
        try {
            PdfWriter.getInstance(documento, new FileOutputStream(fichero));

            documento.open();
            documento.add(new Paragraph(Idioma.getText("Fecha") + " " + fechaActual.toGMTString()));
            documento.add(new Paragraph(Idioma.getText("Analista") + " " + analizador.getAnalizador()));
            Vector temp = analizador.getUnidades();
            Iterator itemp = temp.iterator();
            while (itemp.hasNext()) {
                String unidad = (String) itemp.next();
                if (System.getProperties().getProperty("os.name").startsWith("Windows") || System.getProperties().getProperty("os.name").startsWith("Microsoft")) {

                    documento.add(new Paragraph(Idioma.getText("Ejecutado sobre la unidad") + " " + unidad + " " + " - " + Tools.getSerialVolumeWindows(unidad)));
                } else {
                    documento.add(new Paragraph(Idioma.getText("Ejecutado sobre la unidad") + " " + unidad + " " + " - " + Tools.getSerialVolumeLinux(unidad)));
                }
            }


            Paragraph paragraph = new Paragraph();
            Iterator i = plugins.iterator();
            paragraph.setAlignment(Element.ALIGN_JUSTIFIED);
            while (i.hasNext()) {
                Plugin p = (Plugin) i.next();
                if (p.encontrado()) {
                    documento.add(new Paragraph("Plugin: " + p.get_name()));
                    Chunk underlined = new Chunk("                        ");
                    underlined.setUnderline(0.0f, 0f);
                    documento.add(underlined);
                    documento.add(paragraph);
                    documento.add(new Paragraph(Idioma.getText("COMPROBACIONES"), fonts[10]));
                    documento.add(new Paragraph(" "));
                    Iterator j = p.getTecnicas().iterator();
                    while (j.hasNext()) {
                        documento.add(paragraph);
                        Tecnica tecnica = (Tecnica) j.next();                     
                        if (tecnica.encontrado()) {

                            documento.add(new Phrase("                 " + Idioma.getText("Comprueba si el software esta:") + " ", fonts[8]));
                            documento.add(new Phrase(tecnica._tipo, red));
                            documento.add(paragraph);
                            documento.add(new Phrase("                 " + Idioma.getText("Tecnica que :") + " ", fonts[8]));
                            documento.add(new Phrase(tecnica._tipo_Tecnica, red));
                            documento.add(paragraph);

                            documento.add(new Paragraph("                 " + Idioma.getText("RESULTADOS:"), blue));
                            documento.add(paragraph);
                            if (tecnica._resultados != null) {
                                Iterator k = tecnica._resultados.iterator();
                                while (k.hasNext()) {
                                    Parametro param = (Parametro) k.next();
                                    if (param.getName().compareTo("encontrado") != 0) {
                                        documento.add(new Phrase("                             " + Idioma.getText("Tipo parametro:")));
                                        documento.add(new Phrase(param.getName(), red));
                                        documento.add(paragraph);
                                        documento.add(new Phrase("                             " + Idioma.getText("Valor:") + " "));
                                        documento.add(new Phrase(param.getValue(), red));
                                        documento.add(paragraph);
                                    }
                                }
                            }
                            documento.add(new Paragraph("  "));
                            documento.add(new Paragraph("  "));
                        }
                    }

                    documento.add(new Paragraph("  "));


                    documento.add(new Paragraph("  "));
                    documento.add(new Paragraph("  "));


                    documento.add(new Paragraph(Idioma.getText("ACCIONES"), fonts[10]));
                    documento.add(paragraph);
                    documento.add(new Paragraph("  "));
                    Iterator a = acciones.iterator();
                    while (a.hasNext()) {

                        Accion acc = (Accion) a.next();

                        /*documento.add(new Phrase   ("                 Se realiza porque el software "+ acc._plugin.get_name()+acc._plugin.get_version() + " esta : ",fonts[8]));
                        documento.add(new Phrase ( acc._tipo,red));
                        documento.add(paragraph);*/
                        documento.add(new Phrase("                 " + Idioma.getText("Accion que:") + " ", fonts[8]));
                        documento.add(new Phrase(acc._explicacionAccion, red));

                        Iterator f = acc._resultados.iterator();
                        if (f.hasNext()) {
                            documento.add(new Paragraph("           " + Idioma.getText("Resultados de la accion:")));
                            while (f.hasNext()) {
                                Parametro param2 = (Parametro) f.next();
                                documento.add(new Phrase("                             " + Idioma.getText("Tipo parametro:") + " "));
                                documento.add(new Phrase(param2.getName(), red));
                                documento.add(paragraph);
                                documento.add(new Phrase("                             " + Idioma.getText("Valor:") + " "));
                                documento.add(new Phrase(param2.getValue(), red));
                                documento.add(new Paragraph("  "));
                            }
                        } else {
                            documento.add(new Paragraph("           " + Idioma.getText("No hay resultados asociados a la accion")));
                        }
                    }
                }
            }


                documento.add(paragraph);
                documento.add(new Paragraph(Idioma.getText("Resumen"), fonts[11]));
                documento.add(new Paragraph("  "));
                Chunk underlined = new Chunk("                        ");
                underlined.setUnderline(0.0f, 0f);
                documento.add(underlined);
                Iterator f = plugins.iterator();
                paragraph.setAlignment(Element.ALIGN_JUSTIFIED);

                while (f.hasNext()) {
                    Plugin p = (Plugin) f.next();
                    if (p.instalado()) {
                        documento.add(new Paragraph(Idioma.getText("Se ha encontrado instalado el software ") + " " + p.get_name(), fonts[10]));
                    }else{
                        if (p.desinstalado()) {
                        documento.add(new Paragraph(Idioma.getText("Se ha encontrado desinstalado el software ") + " " + p.get_name(), fonts[10]));
                        }
                    }
                }
            
            documento.newPage();
        } catch (DocumentException de) {
            System.err.println(de.getMessage());
        } catch (IOException ioe) {
            System.err.println(ioe.getMessage());
        }
        documento.close();
    }

    /**
     * Metodo que permite firmar un informe con un fichero certificado PSK12
     * @param fname Nombre del fichero
     * @param fname_out Nombre del fichero de salida
     * @param fileKey Ruta del fichero con la clave
     * @param fileKeyPassword Pasword para firmar con el fichero
     */
    public boolean firmarInforme(String fname, String fname_out, String fileKey, String fileKeyPassword) {

        try {
            // Creacion de un spacio para keys
            KeyStore ks = KeyStore.getInstance("pkcs12");
            // Cargar el fichero p12 con el certificado
            ks.load(new FileInputStream(fileKey), fileKeyPassword.toCharArray());
            String alias = (String) ks.aliases().nextElement();
            // Recuperacion de la clave privada
            PrivateKey key = (PrivateKey) ks.getKey(alias, fileKeyPassword.toCharArray());
            // et de la chaine de certificats
            Certificate[] chain = ks.getCertificateChain(alias);

            // Lectura del documento origen
            PdfReader pdfReader = new PdfReader((new File(fname)).getAbsolutePath());
            File outputFile = new File(fname_out);
            // Firma del documento
            PdfStamper pdfStamper;
            pdfStamper = PdfStamper.createSignature(pdfReader, null, '\0', outputFile);
            PdfSignatureAppearance sap = pdfStamper.getSignatureAppearance();
            sap.setCrypto(key, chain, null, PdfSignatureAppearance.SELF_SIGNED);
            sap.setReason(Idioma.getText("Firmar pdf de analisis forense"));
            sap.setLocation(Idioma.getText("Pais"));

            sap.setVisibleSignature(new Rectangle(10, 10, 50, 30), 1, "null");

            pdfStamper.setFormFlattening(true);
            pdfStamper.close();

            return true;
        } catch (Exception key) {
            key.printStackTrace();
        }
        return false;
    }

    /*
    public void firmarInforme(String fichero_firmado, String fichero_a_firmar, String password) {

    try{
    KeyStore ks = KeyStore.getInstance("pkcs12");
    ks.load(new FileInputStream(""), password.toCharArray());
    String alias = (String)ks.aliases().nextElement();
    PrivateKey key = (PrivateKey)ks.getKey(alias, password.toCharArray());
    Certificate[] chain = ks.getCertificateChain(alias);
    PdfReader reader = new PdfReader(fichero_a_firmar);
    FileOutputStream fout = new FileOutputStream(fichero_firmado);
    PdfStamper stp = PdfStamper.createSignature(reader, fout, '\0');
    PdfSignatureAppearance sap = stp.getSignatureAppearance();
    sap.setCrypto(key, chain, null, PdfSignatureAppearance.WINCER_SIGNED);
    sap.setReason("Generado con AFA");
    sap.setLocation("Spain,AFA(Aplicacion de Analisis Forense)");
    // comment next line to have an invisible signature
    sap.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, null);
    stp.close();
    }
    catch(Exception e){}
    }
     */
}






















